using System;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO.Ports;
using System.IO;

namespace IDCardReaderCSDemo
{
    public partial class Form1 : Form
    {
        public static Boolean IsConnected = false;
        public static Boolean IsAuthenticate = false;
        public static Boolean IsRead_Content = false;
        public static int Port = 0;
        public static int ComPort = 0;
        public const int cbDataSize = 128;
        public const int GphotoSize = 256 * 1024;

        [DllImport("termb.dll")]
        static extern int InitComm(int port);//连接身份证阅读器 

        [DllImport("termb.dll")]
        static extern int InitCommExt();//自动搜索身份证阅读器并连接身份证阅读器 

        [DllImport("termb.dll")]
        static extern int CloseComm();//断开与身份证阅读器连接 

        [DllImport("termb.dll")]
        static extern int Authenticate();//判断是否有放卡，且是否身份证 

        [DllImport("termb.dll")]
        public static extern int Read_Content(int index);//读卡操作,信息文件存储在dll所在下

        [DllImport("termb.dll")]
        public static extern int ReadContent(int index);//读卡操作,信息文件存储在dll所在下

        [DllImport("termb.dll")]
        static extern int GetSAMID(StringBuilder SAMID);//获取SAM模块编号

        [DllImport("termb.dll")]
        static extern int GetSAMIDEx(StringBuilder SAMID);//获取SAM模块编号（10位编号）

        [DllImport("termb.dll")]
        static extern int GetBmpPhoto(string PhotoPath);//解析身份证照片

        [DllImport("termb.dll")]
        static extern int GetBmpPhotoToMem(byte[] imageData, int cbImageData);//解析身份证照片

        [DllImport("termb.dll")]
        static extern int GetBmpPhotoExt();//解析身份证照片

        [DllImport("termb.dll")]
        static extern int Reset_SAM();//重置Sam模块

        [DllImport("termb.dll")]
        static extern int GetSAMStatus();//获取SAM模块状态 

        [DllImport("termb.dll")]
        static extern int GetCardInfo(int index, StringBuilder value);//解析身份证信息 

        [DllImport("termb.dll")]
        static extern int ExportCardImageV();//生成竖版身份证正反两面图片(输出目录：dll所在目录的cardv.jpg和SetCardJPGPathNameV指定路径)

        [DllImport("termb.dll")]
        static extern int ExportCardImageH();//生成横版身份证正反两面图片(输出目录：dll所在目录的cardh.jpg和SetCardJPGPathNameH指定路径) 

        [DllImport("termb.dll")]
        static extern int SetTempDir(string DirPath);//设置生成文件临时目录

        [DllImport("termb.dll")]
        static extern int GetTempDir(StringBuilder path, int cbPath);//获取文件生成临时目录

        [DllImport("termb.dll")]
        static extern void GetPhotoJPGPathName(StringBuilder path, int cbPath);//获取jpg头像全路径名 


        [DllImport("termb.dll")]
        static extern int SetPhotoJPGPathName(string path);//设置jpg头像全路径名

        [DllImport("termb.dll")]
        static extern int SetCardJPGPathNameV(string path);//设置竖版身份证正反两面图片全路径

        [DllImport("termb.dll")]
        static extern int GetCardJPGPathNameV(StringBuilder path, int cbPath);//获取竖版身份证正反两面图片全路径

        [DllImport("termb.dll")]
        static extern int SetCardJPGPathNameH(string path);//设置横版身份证正反两面图片全路径

        [DllImport("termb.dll")]
        static extern int GetCardJPGPathNameH(StringBuilder path, int cbPath);//获取横版身份证正反两面图片全路径

        [DllImport("termb.dll")]
        static extern int getName(StringBuilder data, int cbData);//获取姓名

        [DllImport("termb.dll")]
        static extern int getSex(StringBuilder data, int cbData);//获取性别

        [DllImport("termb.dll")]
        static extern int getNation(StringBuilder data, int cbData);//获取民族

        [DllImport("termb.dll")]
        static extern int getBirthdate(StringBuilder data, int cbData);//获取生日(YYYYMMDD)

        [DllImport("termb.dll")]
        static extern int getAddress(StringBuilder data, int cbData);//获取地址

        [DllImport("termb.dll")]
        static extern int getIDNum(StringBuilder data, int cbData);//获取身份证号

        [DllImport("termb.dll")]
        static extern int getIssue(StringBuilder data, int cbData);//获取签发机关

        [DllImport("termb.dll")]
        static extern int getEffectedDate(StringBuilder data, int cbData);//获取有效期起始日期(YYYYMMDD)

        [DllImport("termb.dll")]
        static extern int getExpiredDate(StringBuilder data, int cbData);//获取有效期截止日期(YYYYMMDD) 

        [DllImport("termb.dll")]
        static extern int getBMPPhotoBase64(StringBuilder data, int cbData);//获取BMP头像Base64编码 

        [DllImport("termb.dll")]
        static extern int getJPGPhotoBase64(StringBuilder data, int cbData);//获取JPG头像Base64编码

        [DllImport("termb.dll")]
        static extern int getJPGCardBase64V(StringBuilder data, int cbData);//获取竖版身份证正反两面JPG图像base64编码字符串

        [DllImport("termb.dll")]
        static extern int getJPGCardBase64H(StringBuilder data, int cbData);//获取横版身份证正反两面JPG图像base64编码字符串

        [DllImport("termb.dll")]
        static extern int HIDVoice(int nVoice);//语音提示。。仅适用于与带HID语音设备的身份证阅读器（如ID200）

        [DllImport("termb.dll")]
        static extern int IC_SetDevNum(int iPort, StringBuilder data, int cbdata);//设置发卡器序列号

        [DllImport("termb.dll")]
        static extern int IC_GetDevNum(int iPort, StringBuilder data, int cbdata);//获取发卡器序列号

        [DllImport("termb.dll")]
        static extern int IC_GetDevVersion(int iPort, StringBuilder data, int cbdata);//设置发卡器序列号 

        [DllImport("termb.dll")]
        static extern int IC_WriteData(int iPort, int keyMode, int sector, int idx, StringBuilder key, StringBuilder data, int cbdata, ref uint snr);//写数据

        [DllImport("termb.dll")]
        static extern int IC_ReadData(int iPort, int keyMode, int sector, int idx, StringBuilder key, StringBuilder data, int cbdata, ref uint snr);//du数据

        [DllImport("termb.dll")]
        static extern int IC_GetICSnr(int iPort, ref uint snr);//读IC卡物理卡号 

        [DllImport("termb.dll")]
        static extern int IC_GetIDSnr(int iPort, StringBuilder data, int cbdata);//读身份证物理卡号 

        [DllImport("termb.dll")]
        static extern int getEnName(StringBuilder data, int cbdata);//获取英文名

        [DllImport("termb.dll")]
        static extern int getCnName(StringBuilder data, int cbdata);//获取中文名 

        [DllImport("termb.dll")]
        static extern int getPassNum(StringBuilder data, int cbdata);//获取港澳台居通行证号码

        [DllImport("termb.dll")]
        static extern int getVisaTimes();//获取签发次数
        
        [DllImport("termb.dll")]
        static extern int IC_ChangeSectorKey(int iPort, int keyMode, int nSector, StringBuilder oldKey, StringBuilder newKey);



        public Form1()
        {
            InitializeComponent();
            for(int i =0;i<16;i++)
            {
                comboBox_Key.Items.Add(""+i);
            }
            for (int i = 0; i < 3; i++)
            {
                comboBox_Clock.Items.Add("" + i);
            }

            string[] sAllPort = null;
            try
            {
                sAllPort = SerialPort.GetPortNames();
                int nPortNu = sAllPort.Length;
                for (int i = 0; i < nPortNu; i++)
                {
                    int nPort = Convert.ToInt32(sAllPort[i].Substring(sAllPort[i].Length - 1, 1));
                    StringBuilder sb = new StringBuilder(cbDataSize);
                    if (1 == IC_GetDevVersion(nPort, sb, cbDataSize))
                    {
                        comboBox_Port.Items.Add(sAllPort[i]);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("获取计算机COM口列表失败!\r\n错误信息:" + ex.Message);
            }
        }

        private void button_Connect_Click(object sender, EventArgs e)
        {
            int AutoSearchReader = InitCommExt();
            if (AutoSearchReader > 0)
            {
                Port = AutoSearchReader;
                IsConnected = true;
                textBox_Name.Text = AutoSearchReader.ToString();

                StringBuilder sb = new StringBuilder(cbDataSize);
                GetSAMID(sb);
                MessageBox.Show("连接身份证阅读器成功,SAM模块编号:" + sb);
                button_Connect.Enabled = false;
                button_ReadCard.Enabled = true;
                button_DisConnect.Enabled = true;
                return;
            }
            else
            {
                MessageBox.Show("检查是否正确连接设备");
            }
        }
        public void ClearData()
        {
            textBox_Name.Text = "";
            textBox_NationOrCountry.Text = "";
            textBox_Sex.Text = "";
            textBox_VisaTimes.Text = "";
            textBox_PassNum.Text = "";
            textBox_Name.Text = "";
            textBox_Issue.Text = "";
            textBox_IDCardNum.Text = "";
            textBox_ExpiredDate.Text = "";
            textBox_CardType.Text = "";
            textBox_BornDate.Text = "";
            textBox_Address.Text = "";
            textBox_BornDate.Text = "";
            pictureBox_TouXiang.Image = null;
        }
        private void button_ReadCard_Click(object sender, EventArgs e)
        {
            //卡认证
            int FindCard = Authenticate();
            if (FindCard != 1)
            {
                ClearData();
                return;
            }
            //读卡
            int rs = Read_Content(1);
            if (rs != 1 && rs != 2 && rs != 3)
            {
                ClearData();
                return;
            }

            //读卡成功
            //姓名
            StringBuilder sb = new StringBuilder(cbDataSize);
            getName(sb, cbDataSize);
            textBox_Name.Text = sb.ToString();

            //民族/国家
            getNation(sb, cbDataSize);
            textBox_NationOrCountry.Text = sb.ToString();

            //性别 
            getSex(sb, cbDataSize);
            textBox_Sex.Text = sb.ToString();

            //出生 
            getBirthdate(sb, cbDataSize);
            textBox_BornDate.Text = sb.ToString();
            // sb.ToString().Substring(0, 4) - sb.ToString().Substring(4, 2) - sb.ToString().Substring(6, 2);

            //地址 
            getAddress(sb, cbDataSize);
            string ad = sb.ToString();
            textBox_Address.Text = ad;

            //号码 
            getIDNum(sb, cbDataSize);
            textBox_IDCardNum.Text = sb.ToString();

            //机关 
            getIssue(sb, cbDataSize);
            textBox_Issue.Text = sb.ToString();

            //有效期 
            getEffectedDate(sb, cbDataSize);
            string aa = sb.ToString();
            getExpiredDate(sb, cbDataSize);
            textBox_ExpiredDate.Text = aa + sb.ToString();

            //通行证号  
            getPassNum(sb, cbDataSize);
            textBox_PassNum.Text = sb.ToString();

            //签证次数  
            textBox_VisaTimes.Text = "" + getVisaTimes();

            //英文名 
            getEnName(sb, cbDataSize);
            textBox_EnName.Text = sb.ToString();

            //中文名  
            getCnName(sb, cbDataSize);
            textBox_CnName.Text = sb.ToString();

            //证件类型
            GetCardInfo(105, sb);
            if ("1" == sb.ToString())
            {
                textBox_CardType.Text = "居民身份证";
            }
            else if ("3" == sb.ToString())
            {
                textBox_CardType.Text = "港澳台居住证";
            }
            else
            {
                textBox_CardType.Text = "外国人居住证";
            }

            //显示头像
            GetBmpPhotoExt();
            int cbPhoto = 256 * 1024;
            StringBuilder sbPhoto = new StringBuilder(cbPhoto);
            int nRet = getBMPPhotoBase64(sbPhoto, cbPhoto);
            byte[] byPhoto = Convert.FromBase64String(sbPhoto.ToString());
 
            if (nRet == 1)
                {
                    MemoryStream ms = new MemoryStream(byPhoto);
                    Image a = Image.FromStream(ms);

                    pictureBox_TouXiang.Image = a;
                }
        }

        private void button_DisConnect_Click(object sender, EventArgs e)
        {
            ClearData();
            button_Connect.Enabled = true;
            button_ReadCard.Enabled = false;
            button_DisConnect.Enabled = false;
        }

        private void button_ReadIcCard_Click(object sender, EventArgs e)
        {
            if (comboBox_Key.SelectedIndex == -1 || comboBox_Clock.SelectedIndex == -1 || comboBox_Port.SelectedIndex == -1 || textBox_Key.Text.Trim() == String.Empty)
            {
                textBox_Tip.Text = "Please check input";
                return;
            }
            string  strPort = comboBox_Port.SelectedItem.ToString();
            int nPort = Convert.ToInt32(strPort.Substring(strPort.Length - 1, 1));
            StringBuilder key = new StringBuilder(textBox_Key.Text);
            StringBuilder data = new StringBuilder(256);
            uint snr = 0;
            int rs = IC_ReadData(nPort, 0, comboBox_Key.SelectedIndex + 1, comboBox_Clock.SelectedIndex, key, data, 256, ref snr);
            if (rs == 1)
            {
                textBox_Tip.Text = data.ToString().Trim();
            }
            else
            {
                textBox_Tip.Text = "IC_ReadData : Fail";
            }
        }

        private void button_WriteIcCard_Click(object sender, EventArgs e)
        {
            if (comboBox_Key.SelectedIndex == -1 || comboBox_Clock.SelectedIndex == -1 || comboBox_Port.SelectedIndex == -1 || textBox_Key.Text.Trim() == String.Empty)
            {
                textBox_Tip.Text = "Please check input";
                return;
            }

            string strPort = comboBox_Port.SelectedItem.ToString();
            int nPort = Convert.ToInt32(strPort.Substring(strPort.Length - 1, 1));
            StringBuilder key = new StringBuilder(textBox_Key.Text);
            StringBuilder data = new StringBuilder(textBox_WriteIcData.Text);
            uint snr = 0;
            if (data.Length != 32)
            {
                MessageBox.Show("请输入32位的16进制字符(16字节数据)");
                return;
            }
            int rs = IC_WriteData(nPort, 0, comboBox_Key.SelectedIndex+1, comboBox_Clock.SelectedIndex, key, data, data.Length, ref snr);
            if (rs == 1)
            {
                textBox_Tip.Text = "IC_WriteData :  Success";
            }
            else
            {
                textBox_Tip.Text = "IC_WriteData : Fail";
            }

        }

        private void button_GetIcSnr_Click(object sender, EventArgs e)
        {
            if (comboBox_Port.SelectedIndex == -1)
            {
                textBox_Tip.Text = "Please check input";
                return;
            }
            string strPort = comboBox_Port.SelectedItem.ToString();
            int nPort = Convert.ToInt32(strPort.Substring(strPort.Length - 1, 1));
            uint snr = 0;
            int aa = IC_GetICSnr(nPort, ref snr);
            if (aa == 1)
            {
                textBox_Tip.Text = snr.ToString();
            }
            else
            {
                textBox_Tip.Text = "IC_GetICSnr : Fail";
            }
        }

        private void button_GetIdSnr_Click(object sender, EventArgs e)
        {
            if (comboBox_Port.SelectedIndex == -1)
            {
                textBox_Tip.Text = "Please check input";
                return;
            }
            string strPort = comboBox_Port.SelectedItem.ToString();
            int nPort = Convert.ToInt32(strPort.Substring(strPort.Length - 1, 1));            
            StringBuilder sb = new StringBuilder(cbDataSize);
            int aa = IC_GetIDSnr(nPort, sb, cbDataSize);
            if (aa == 1)
            {
                textBox_Tip.Text = sb.ToString();
            }
            else
            {
                textBox_Tip.Text = "IC_GetIDSnr : Fail";
            }
        }

        private void button_GetIdDN_Click(object sender, EventArgs e)
        {
            if (comboBox_Port.SelectedIndex == -1)
            {
                textBox_Tip.Text = "Please check input";
                return;
            }

            string strPort = comboBox_Port.SelectedItem.ToString();
            int nPort = Convert.ToInt32(strPort.Substring(strPort.Length - 1, 1));  
            StringBuilder sb = new StringBuilder(cbDataSize);
            int rs = IC_GetDevNum(nPort, sb, cbDataSize);
            if (rs == 1)
            {
                string tempStr = sb.ToString();
                textBox_Tip.Text = tempStr;
                //tempStr = tempStr.Substring(0, 12);
                //Int64 abc = Int64.Parse(tempStr);
                //textBox_Tip.Text = string.Format("{0:x12}", abc);
                //textBox_Tip.Text = "IC_GetDevNum : Success";
            }
            else
            {
                textBox_Tip.Text = "IC_GetDevNum : Fail";
            }
        }

        private void button_ChangeKey_Click(object sender, EventArgs e)
        {
            //IC_ChangeSectorKey(int iPort, int keyMode, int nSector, char *oldKey, char *newKey);

            if (comboBox_Key.SelectedIndex == -1 || comboBox_Clock.SelectedIndex == -1 || comboBox_Port.SelectedIndex == -1)
            {
                textBox_Tip.Text = "Please check input";
                return;
            }

            string strPort = comboBox_Port.SelectedItem.ToString();
            int nPort = Convert.ToInt32(strPort.Substring(strPort.Length - 1, 1));  
            StringBuilder oldKey = new StringBuilder(textBox_Key.Text);
            StringBuilder newKey = new StringBuilder("123456789012");

            int rs = IC_ChangeSectorKey(nPort, comboBox_Key.SelectedIndex + 1, comboBox_Clock.SelectedIndex, oldKey, newKey);
            if (rs == 1)
            {
                textBox_Tip.Text = "改密成功";
            }
            else
            {
                textBox_Tip.Text = "改密失败";
            }
        }
    }
}
